package com.qingsong.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.mybatisflex.core.query.QueryChain;
import com.mybatisflex.core.update.UpdateChain;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.qingsong.dto.CouponsInsertDTO;
import com.qingsong.dto.CouponsPageDTO;
import com.qingsong.dto.CouponsUpdateDTO;
import com.qingsong.entity.Coupons;
import com.qingsong.exception.ServiceException;
import com.qingsong.mapper.CouponsMapper;
import com.qingsong.service.CouponsService;
import com.qingsong.vo.CouponsSimpleListVO;
import org.springframework.stereotype.Service;
import com.mybatisflex.core.paginate.Page;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.List;
import static com.qingsong.entity.table.CouponsTableDef.COUPONS;
import static com.qingsong.entity.table.CourseTableDef.COURSE;


/**
 *  服务层实现。
 *
 * @author NXD003
 * @since 2024-12-22
 */
@Service
@CacheConfig(cacheNames = "coupons")
public class CouponsServiceImpl extends ServiceImpl<CouponsMapper, Coupons>  implements CouponsService{


    @CacheEvict(allEntries = true)
    @Override
    public boolean insert(CouponsInsertDTO dto) {
        if (QueryChain.of(mapper)
                .where(COUPONS.TITLE.eq(dto.getTitle()))
                .exists()) {
            throw new ServiceException("标题已存在");
        }
        if (QueryChain.of(mapper)
                .where(COUPONS.CODE.eq(dto.getCode()))
                .exists()) {
            throw new ServiceException("兑换码已存在");
        }
        // 组装 entity 实体类
        Coupons Coupons = BeanUtil.copyProperties(dto, Coupons.class);
        // 判断生效时间和失效时间是否合理
        if (dto.getStartTime().isAfter(dto.getEndTime())) {
            throw new ServiceException("生效时间不能在失效时间之后");
        }
        Coupons.setCreated(LocalDateTime.now());
        Coupons.setUpdated(LocalDateTime.now());
        return mapper.insert(Coupons) > 0;
    }

    @Cacheable(key = "#p0",
            condition = "#p0 != null",
            unless = "#result == null")
    @Override
    public Coupons select(Long id) {
        return mapper.selectOneWithRelationsById(id);
    }

    @Override
    @Cacheable(key = "#root.methodName",
            unless = "#result == null")
    public List<Coupons> list() {
        return QueryChain.of(mapper)
                .orderBy(COUPONS.ID.asc(), COUPONS.ID.desc())
                .withRelations()
                .list();
    }
    @Cacheable(key = "#root.methodName",
            unless = "#result == null")
    @Override
    public List<Coupons> top(Long n) {

        return QueryChain.of(mapper)
                .orderBy(COUPONS.ID.asc(), COUPONS.ID.desc())
                .limit(n)
                .withRelations()
                .list();
    }

    @Override
    @Cacheable(key = "#root.methodName + ':' + #p0.toString()", condition = "#p0 != null", unless = "#result == null")
    public Page<Coupons> page(CouponsPageDTO dto) {
        QueryChain<Coupons> queryChain = QueryChain.of(mapper)
                .orderBy(COUPONS.ID.asc(), COUPONS.ID.desc());
        // title 条件
        String title = dto.getTitle();
        if (ObjectUtil.isNotNull(title)) {
            queryChain.where(COUPONS.TITLE.like(title));
        }
        // code 条件
        String code = dto.getCode();
        if (ObjectUtil.isNotNull(code)) {
            queryChain.where(COUPONS.CODE.like(code));
        }
        return queryChain.withRelations()
                .page(new Page<>(dto.getPageNum(), dto.getPageSize()));
    }

    @CacheEvict(allEntries = true)
    @Override
    public boolean update(CouponsUpdateDTO dto) {
        if (QueryChain.of(mapper)
                .where(COUPONS.TITLE.eq(dto.getTitle()))
                .exists()) {
            throw new ServiceException("标题已存在");
        }
        if (QueryChain.of(mapper)
                .where(COUPONS.CODE.eq(dto.getCode()))
                .exists()) {
            throw new ServiceException("兑换码已存在");
        }
        // 组装 entity 实体类
        Coupons coupons = BeanUtil.copyProperties(dto, Coupons.class);
        // 判断生效时间和失效时间是否合理
        if (dto.getStartTime().isAfter(dto.getEndTime())) {
            throw new ServiceException("生效时间不能在失效时间之后");
        }
        coupons.setUpdated(LocalDateTime.now());
        return UpdateChain.of(coupons)
                .where(COUPONS.ID.eq(coupons.getId()))
                .update();
    }

    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(allEntries = true)
    @Override
    public boolean delete(Long id) {
        return mapper.deleteById(id) > 0;
    }

    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(allEntries = true)
    @Override
    public boolean deleteBatch(List<Long> ids) {
        // 批量删除课程
        return mapper.deleteBatchByIds(ids) > 0;
    }
    @Cacheable(key = "#root.methodName", unless = "#result == null")
    @Override
    public List<CouponsSimpleListVO> simpleList() {
        return QueryChain.of(mapper)
                .withRelations()
                .listAs(CouponsSimpleListVO.class);
    }

    @Cacheable(key = "#root.methodName + ':' + #p0",
            condition = "#p0 != null",
            unless = "#result == null")
    @Override
    public Coupons selectByCode(String code) {
        return QueryChain.of(mapper)
                .where(COUPONS.CODE.eq(code))
                .withRelations()
                .one();
    }

}